package com.applcn.core.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.DefaultLifecycleProcessor;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 优雅停机Filter
 *
 * @author xsg
 */
@Component
@Slf4j
public class ShutdownFilter implements Filter, ApplicationContextAware {
    private static String token;
    private static ApplicationContext context;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        token = filterConfig.getInitParameter("token");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        //获取请求中的token
        String reqToken = request.getParameter("token");
        if (!token.equals(reqToken)) {
            response.setStatus(403);
            response.getWriter().write("NG");
            return;
        }

        log.info("------------- begin to shut down ----------");
        //执行优雅停机
        this.executeShutdown();
        response.setStatus(200);
        response.getWriter().write("OK");
    }

    @Override
    public void destroy() {
        // no op
    }

    private void executeShutdown() {
        Thread thread = new Thread(this::performShutdown);
        thread.setContextClassLoader(this.getClass().getClassLoader());
        thread.start();
    }

    private void performShutdown() {
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException var2) {
            Thread.currentThread().interrupt();
        }
        //
        DefaultLifecycleProcessor d = context.getBean(DefaultLifecycleProcessor.class);
        d.setTimeoutPerShutdownPhase(3000L);
        //
        ((ConfigurableApplicationContext) context).close();
        log.info("-------------end of shutdown----------------------");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
}
